/*
 * Copyright © 2019-2020  Whale Cloud, Inc. All Rights Reserved.
 *
 * Notice: Whale Cloud Inc copyrights this specification.
 * No part of this specification may be reproduced in any form or means,
 * without the prior written consent of Whale Cloud Inc.
 *
 */
package com.wteam.modules.system.service.impl;

import com.google.common.collect.Sets;
import com.wteam.modules.security.service.JwtUserDetailsService;
import com.wteam.modules.security.service.OnlineUserService;
import com.wteam.modules.system.config.LoginType;
import com.wteam.modules.system.domain.Role;
import com.wteam.modules.system.domain.User;
import com.wteam.modules.system.domain.dto.CusPage;
import com.wteam.modules.system.domain.dto.TeacherSubmitDTO;
import com.wteam.modules.system.domain.mapper.UserMapper;
import com.wteam.modules.system.repository.UserRepository;
import com.wteam.modules.system.service.TeacherService;
import com.wteam.modules.system.domain.Teacher;
import com.wteam.modules.system.domain.dto.TeacherDTO;
import com.wteam.modules.system.domain.criteria.TeacherQueryCriteria;
import com.wteam.modules.system.domain.mapper.TeacherMapper;
import com.wteam.modules.system.repository.TeacherRepository;
import com.wteam.modules.system.service.UserService;
import com.wteam.utils.*;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.cache.annotation.*;
import lombok.RequiredArgsConstructor;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

/**
 * 教师 业务实现层.
 *
 * @author herry_wong
 * @since 2020-12-28
 */
@Service
@RequiredArgsConstructor
@CacheConfig(cacheNames = "teacher")
@Transactional(readOnly = true, rollbackFor = Exception.class)
public class TeacherServiceImpl implements TeacherService {

    private final TeacherRepository teacherRepository;
    private final TeacherMapper teacherMapper;

    private final UserRepository userRepository;
    private final UserMapper userMapper;

    private final RedisUtils redisUtils;

    private final PasswordEncoder passwordEncoder;

    private final OnlineUserService onlineUserService;

    private final UserService userService;

    @Override
    public Map<String,Object> queryAll(TeacherQueryCriteria criteria, Pageable pageable){
        Page<Teacher> page = teacherRepository.findAll((root, criteriaQuery, criteriaBuilder) ->  QueryHelper.andPredicate(root, criteria, criteriaBuilder), pageable);
        Page<TeacherDTO> teacherDTOPage = page.map(teacherMapper::toDto);
        Page<TeacherDTO> cusPage = new CusPage<>(teacherDTOPage);
        for (TeacherDTO teacherDTO: cusPage){
            Collections.replaceAll(cusPage.getContent(),teacherDTO,findDTOById(teacherDTO.getUid()));
        }
        return PageUtil.toPage(cusPage);
    }

    @Override
    public List<TeacherDTO> queryAll(TeacherQueryCriteria criteria){
        return teacherMapper.toDto(teacherRepository.findAll((root, criteriaQuery, criteriaBuilder) ->  QueryHelper.andPredicate(root,criteria,criteriaBuilder)));
    }

    @Override
//    @Cacheable(key = "'id:' + #p0")
    public TeacherDTO findDTOById(Long uid) {
        Teacher teacher = teacherRepository.findById(uid).orElse(null);
        ValidUtil.notNull(teacher, Teacher.ENTITY_NAME, "uid", uid);
        TeacherDTO teacherDTO = teacherMapper.toDto(teacher);
        teacherDTO.setUserDTO(userMapper.toDto(userRepository.findById(teacher.getUid()).orElse(null)));
        return teacherDTO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public TeacherDTO create(TeacherSubmitDTO resources) {
        Teacher teacher = new Teacher();
        resources.getUser().setLoginType(LoginType.LOGIN_SYSTEM);
        resources.getUser().setEnabled(true);
        resources.getUser().setRoles(Sets.newHashSet(new Role(2L)));
        resources.getUser().setPassword(passwordEncoder.encode("123456"));
        User user = userRepository.save(resources.getUser());

        teacher.setUid(user.getId());
        teacher = teacherRepository.save(teacher);
        TeacherDTO teacherDTO = teacherMapper.toDto(teacher);
        teacherDTO.setUserDTO(userMapper.toDto(user));
        return teacherDTO;
    }

    @Override
    @CacheEvict(key = "'id:' + #p0.id")
    @Transactional(rollbackFor = Exception.class)
    public void update(TeacherSubmitDTO resources) {
        Teacher teacher = teacherRepository.findById(resources.getUser().getId()).orElse(null);
        User user = userRepository.findById(resources.getUser().getId()).orElse(null);
        ValidUtil.notNull(teacher, Teacher.ENTITY_NAME, "id",resources.getUser().getId());

        user.copy(resources.getUser());
        if (resources.getUser().getPassword() != null&&!resources.getUser().getPassword().equals("")){
            user.setPassword(passwordEncoder.encode(resources.getUser().getPassword()));
            redisUtils.del("user::loadUserByUsername:"+user.getUsername());
            JwtUserDetailsService.removeUser(user.getUsername());
            onlineUserService.checkLoginOnUser(user.getUsername(),null);
        }
        user.copy(resources.getUser());
        userRepository.save(user);
        teacherRepository.save(teacher);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteAll(Set<Long> ids) {
        redisUtils.delByKeys("teacher::id:", ids);
        teacherRepository.logicDeleteInBatchById(ids);
        for (Long id: ids){
            userService.deleteOne(id);
        }
    }

    @Override
    public void download(List<TeacherDTO> queryAll, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (TeacherDTO teacher : queryAll) {
            Map<String, Object> map = new LinkedHashMap<>();
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }
}